home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / src / parse.y < prev    next >
Text File  |  1997-07-20  |  57KB  |  2,428 lines

  1. /*
  2.  
  3. Copyright (C) 1996 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. /* Modified by Klaus Gebhardt, 1996 */
  24.  
  25. // Parser for Octave.
  26.  
  27. // C decarations.
  28.  
  29. %{
  30. #define YYDEBUG 1
  31.  
  32. #ifdef HAVE_CONFIG_H
  33. #include <config.h>
  34. #endif
  35.  
  36. #ifdef YYBYACC
  37. #include <cstdlib>
  38. #endif
  39.  
  40. #include <strstream.h>
  41.  
  42. #include "Matrix.h"
  43.  
  44. #include "defun.h"
  45. #include "error.h"
  46. #include "input.h"
  47. #include "lex.h"
  48. #include "oct-hist.h"
  49. #include "toplev.h"
  50. #include "pager.h"
  51. #include "parse.h"
  52. #include "pt-cmd.h"
  53. #include "pt-const.h"
  54. #include "pt-fcn.h"
  55. #include "pt-fvc.h"
  56. #include "pt-mat.h"
  57. #include "pt-mvr.h"
  58. #include "pt-exp.h"
  59. #include "pt-misc.h"
  60. #include "pt-plot.h"
  61. #include "pt-pr-code.h"
  62. #include "symtab.h"
  63. #include "token.h"
  64. #include "utils.h"
  65. #include "variables.h"
  66.  
  67. // If TRUE, generate a warning for the assignment in things like
  68. //
  69. //   octave> if (a = 2 < n)
  70. //
  71. // but not
  72. //
  73. //   octave> if ((a = 2) < n)
  74. //
  75. static bool Vwarn_assign_as_truth_value;
  76.  
  77. // If TRUE, generate a warning for variable swich labels.
  78. static bool Vwarn_variable_switch_label;
  79.  
  80. // If TRUE, generate a warning for the comma in things like
  81. //
  82. //   octave> global a, b = 2
  83. //
  84. static bool Vwarn_comma_in_global_decl;
  85.  
  86. // If TRUE, generate warning if declared function name disagrees with
  87. // the name of the file in which it is defined.
  88. static bool Vwarn_function_name_clash;
  89.  
  90. // If TRUE, generate warning if a statement in a function is not
  91. // terminated with a semicolon.  Useful for checking functions that
  92. // should only produce output using explicit printing statements.
  93. static bool Vwarn_missing_semicolon;
  94.  
  95. // Temporary symbol table pointer used to cope with bogus function syntax.
  96. symbol_table *tmp_local_sym_tab = 0;
  97.  
  98. // The current input line number.
  99. int input_line_number = 0;
  100.  
  101. // The column of the current token.
  102. int current_input_column = 1;
  103.  
  104. // Buffer for help text snagged from function files.
  105. string help_buf;
  106.  
  107. // Forward declarations for some functions defined at the bottom of
  108. // the file.
  109.  
  110. // Generic error messages.
  111. static void yyerror (char *s);
  112.  
  113. // Error mesages for mismatched end tokens.
  114. static void end_error (char *type, token::end_tok_type ettype, int l, int c);
  115.  
  116. // Check to see that end tokens are properly matched.
  117. static int check_end (token *tok, token::end_tok_type expected);
  118.  
  119. // Try to figure out early if an expression should become an
  120. // assignment to the built-in variable ans.
  121. static tree_expression *maybe_convert_to_ans_assign (tree_expression *expr);
  122.  
  123. // Maybe print a warning if an assignment expression is used as the
  124. // test in a logical expression.
  125. static void maybe_warn_assign_as_truth_value (tree_expression *expr);
  126.  
  127. // Maybe print a warning about switch labels that aren't constants.
  128. static void maybe_warn_variable_switch_label (tree_expression *expr);
  129.  
  130. // Create a plot command.
  131. static tree_plot_command *make_plot_command
  132.      (token *tok, plot_limits *range, subplot_list *list);
  133.  
  134. // Finish building a range.
  135. static tree_expression *finish_colon_expression (tree_colon_expression *e);
  136.  
  137. // Build a constant.
  138. static tree_constant *make_constant (int op, token *tok_val);
  139.  
  140. // Build a binary expression.
  141. static tree_expression *make_binary_op
  142.      (int op, tree_expression *op1,    token *tok_val, tree_expression *op2);
  143.  
  144. // Build a boolean expression.
  145. static tree_expression *make_boolean_op
  146.      (int op, tree_expression *op1,    token *tok_val, tree_expression *op2);
  147.  
  148. // Build a prefix expression.
  149. static tree_expression *make_prefix_op
  150.      (int op, tree_identifier *op1, token *tok_val);
  151.  
  152. // Build a postfix expression.
  153. static tree_expression *make_postfix_op
  154.      (int op, tree_identifier *op1, token *tok_val);
  155.  
  156. // Build a binary expression.
  157. static tree_expression *make_unary_op
  158.      (int op, tree_expression *op1, token *tok_val);
  159.  
  160. // Build an unwind-protect command.
  161. static tree_command *make_unwind_command
  162.      (token *unwind_tok, tree_statement_list *body,
  163.       tree_statement_list *cleanup, token *end_tok);
  164.  
  165. // Build a try-catch command.
  166. static tree_command *make_try_command
  167.      (token *try_tok, tree_statement_list *body,
  168.       tree_statement_list *cleanup, token *end_tok);
  169.  
  170. // Build a while command.
  171. static tree_command *make_while_command
  172.      (token *while_tok, tree_expression *expr,
  173.       tree_statement_list *body, token *end_tok);
  174.  
  175. // Build a for command.
  176. static tree_command *make_for_command
  177.      (token *for_tok, tree_index_expression *var,
  178.       tree_expression *expr, tree_statement_list *body,
  179.       token *end_tok);
  180.  
  181. // Build a for command a different way.
  182. static tree_command *make_for_command
  183.      (token *for_tok, tree_matrix_row *mr, tree_expression *expr,
  184.       tree_statement_list *body, token *end_tok);
  185.  
  186. // Build a break command.
  187. static tree_command *make_break_command (token *break_tok);
  188.  
  189. // Build a continue command.
  190. static tree_command *make_continue_command (token *continue_tok);
  191.  
  192. // Build a return command.
  193. static tree_command *make_return_command (token *return_tok);
  194.  
  195. // Start an if command.
  196. static tree_if_command_list *start_if_command
  197.      (tree_expression *expr, tree_statement_list *list);
  198.  
  199. // Finish an if command.
  200. static tree_if_command *finish_if_command
  201.      (token *if_tok, tree_if_command_list *list, token *end_tok);
  202.  
  203. // Build an elseif clause.
  204. static tree_if_clause *make_elseif_clause
  205.      (tree_expression *expr, tree_statement_list *list);
  206.  
  207. // Finish a switch command.
  208. static tree_switch_command *finish_switch_command
  209.      (token *switch_tok, tree_expression *expr,
  210.       tree_switch_case_list *list, token *end_tok);
  211.  
  212. // Build a switch case.
  213. static tree_switch_case *make_switch_case
  214.      (tree_expression *expr, tree_statement_list *list);
  215.  
  216. // Build an assignment to a variable.
  217. static tree_expression *make_simple_assignment
  218.      (tree_index_expression *var, token *eq_tok, tree_expression *expr);
  219.  
  220. // Make an expression that handles assignment of multiple values.
  221. static tree_expression *make_multi_val_ret
  222.      (tree_matrix_row *mr, tree_expression *rhs, token *eq_tok);
  223.  
  224. // Begin defining a function.
  225. static tree_function *start_function_def
  226.      (tree_parameter_list *param_list, tree_statement_list *body);
  227.  
  228. // Do most of the work for defining a function.
  229. static tree_function *frob_function_def
  230.      (tree_identifier *id, tree_function *fcn);
  231.  
  232. // Finish defining a function.
  233. static tree_function *finish_function_def (token *var, tree_function *fcn);
  234.  
  235. // Finish defining a function a different way.
  236. static tree_function *finish_function_def
  237.      (tree_parameter_list *ret_list, tree_function *fcn);
  238.  
  239. // Make an index expression.
  240. static tree_index_expression *make_index_expression
  241.      (tree_indirect_ref *indir, tree_argument_list *args);
  242.  
  243. // Finish building a matrix list.
  244. static tree_expression *finish_matrix (tree_matrix *m);
  245.  
  246. // Maybe print a warning.  Duh.
  247. static void maybe_warn_missing_semi (tree_statement_list *);
  248.  
  249. // Set the print flag for a statement based on the separator type.
  250. static void set_stmt_print_flag (tree_statement_list *, char, bool);
  251.  
  252. #define ABORT_PARSE \
  253.   do \
  254.     { \
  255.       global_command = 0; \
  256.       yyerrok; \
  257.       if (interactive || forced_interactive || really_forced_interactive) \
  258.     YYACCEPT; \
  259.       else \
  260.     YYABORT; \
  261.     } \
  262.   while (0)
  263.  
  264. %}
  265.  
  266. // Bison declarations.
  267.  
  268. %union
  269. {
  270. // The type of the basic tokens returned by the lexer.
  271.   token *tok_val;
  272.  
  273. // Types for the nonterminals we generate.
  274.   char sep_type;
  275.   tree *tree_type;
  276.   tree_matrix *tree_matrix_type;
  277.   tree_matrix_row *tree_matrix_row_type;
  278.   tree_expression *tree_expression_type;
  279.   tree_constant *tree_constant_type;
  280.   tree_identifier *tree_identifier_type;
  281.   tree_indirect_ref *tree_indirect_ref_type;
  282.   tree_function *tree_function_type;
  283.   tree_index_expression *tree_index_expression_type;
  284.   tree_colon_expression *tree_colon_expression_type;
  285.   tree_argument_list *tree_argument_list_type;
  286.   tree_parameter_list *tree_parameter_list_type;
  287.   tree_command *tree_command_type;
  288.   tree_if_command *tree_if_command_type;
  289.   tree_if_clause *tree_if_clause_type;
  290.   tree_if_command_list *tree_if_command_list_type;
  291.   tree_switch_command *tree_switch_command_type;
  292.   tree_switch_case *tree_switch_case_type;
  293.   tree_switch_case_list *tree_switch_case_list_type;
  294.   tree_global *tree_global_type;
  295.   tree_global_init_list *tree_global_init_list_type;
  296.   tree_global_command *tree_global_command_type;
  297.   tree_statement *tree_statement_type;
  298.   tree_statement_list *tree_statement_list_type;
  299.   tree_plot_command *tree_plot_command_type;
  300.   subplot *subplot_type;
  301.   subplot_list *subplot_list_type;
  302.   plot_limits *plot_limits_type;
  303.   plot_range *plot_range_type;
  304.   subplot_using *subplot_using_type;
  305.   subplot_style *subplot_style_type;
  306. }
  307.  
  308. // Tokens with line and column information.
  309. %token <tok_val> '=' ':' '-' '+' '*' '/'
  310. %token <tok_val> EXPR_AND_AND EXPR_OR_OR
  311. %token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
  312. %token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
  313. %token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV EPLUS EMINUS
  314. %token <tok_val> QUOTE TRANSPOSE
  315. %token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
  316. %token <tok_val> NUM IMAG_NUM
  317. %token <tok_val> NAME SCREW
  318. %token <tok_val> END
  319. %token <tok_val> PLOT
  320. %token <tok_val> TEXT STYLE
  321. %token <tok_val> FOR WHILE
  322. %token <tok_val> IF ELSEIF ELSE
  323. %token <tok_val> SWITCH CASE OTHERWISE
  324. %token <tok_val> BREAK CONTINUE FUNC_RET
  325. %token <tok_val> UNWIND CLEANUP
  326. %token <tok_val> TRY CATCH
  327. %token <tok_val> GLOBAL
  328. %token <tok_val> TEXT_ID
  329.  
  330. // Other tokens.
  331. %token LEXICAL_ERROR
  332. %token FCN SCREW_TWO
  333. %token ELLIPSIS
  334. %token ALL_VA_ARGS
  335. %token END_OF_INPUT
  336. %token USING TITLE WITH COLON OPEN_BRACE CLOSE_BRACE CLEAR
  337.  
  338. // Nonterminals we construct.
  339. %type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep
  340. %type <tree_type> input
  341. %type <tree_matrix_type> rows rows1
  342. %type <tree_matrix_row_type> matrix_row matrix_row1
  343. %type <tree_expression_type> expression simple_expr simple_expr1
  344. %type <tree_expression_type> ans_expression title matrix
  345. %type <tree_identifier_type> identifier
  346. %type <tree_indirect_ref_type> indirect_ref indirect_ref1
  347. %type <tree_function_type> func_def1 func_def2 func_def3
  348. %type <tree_index_expression_type> variable word_list_cmd
  349. %type <tree_colon_expression_type> colon_expr
  350. %type <tree_argument_list_type> arg_list word_list
  351. %type <tree_parameter_list_type> param_list param_list1
  352. %type <tree_parameter_list_type> return_list return_list1
  353. %type <tree_command_type> command func_def
  354. %type <tree_if_command_type> if_command
  355. %type <tree_if_clause_type> elseif_clause else_clause
  356. %type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
  357. %type <tree_switch_command_type> switch_command
  358. %type <tree_switch_case_type> switch_case default_case
  359. %type <tree_switch_case_list_type> case_list1 case_list
  360. %type <tree_global_type> global_decl2
  361. %type <tree_global_init_list_type> global_decl1
  362. %type <tree_global_command_type> global_decl
  363. %type <tree_statement_type> statement
  364. %type <tree_statement_list_type> simple_list simple_list1 list list1
  365. %type <tree_statement_list_type> opt_list input1
  366. %type <tree_plot_command_type> plot_command 
  367. %type <subplot_type> plot_command2 plot_options
  368. %type <subplot_list_type> plot_command1
  369. %type <plot_limits_type> ranges
  370. %type <plot_range_type> ranges1 
  371. %type <subplot_using_type> using using1 
  372. %type <subplot_style_type> style
  373.  
  374. // Precedence and associativity.
  375. %left ';' ',' '\n' '\r' ''
  376. %right '='
  377. %left EXPR_AND_AND EXPR_OR_OR
  378. %left EXPR_AND EXPR_OR
  379. %left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
  380. %left ':'
  381. %left '-' '+' EPLUS EMINUS
  382. %left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
  383. %left QUOTE TRANSPOSE
  384. %left UNARY PLUS_PLUS MINUS_MINUS EXPR_NOT
  385. %right POW EPOW
  386.  
  387. // There are 18 shift/reduce conflicts, ok?  But this only works with
  388. // bison...
  389. // %expect 18
  390.  
  391. // Where to start.
  392. %start input
  393.  
  394. // Grammar rules.
  395.  
  396. %%
  397.  
  398. input        : input1
  399.           {
  400.             global_command = $1;
  401.             promptflag = 1;
  402.             YYACCEPT;
  403.           }
  404.         | END_OF_INPUT
  405.           {
  406.             global_command = 0;
  407.             promptflag = 1;
  408.             YYABORT;
  409.           }
  410.         | simple_list parse_error
  411.           { ABORT_PARSE; }
  412.         | parse_error
  413.           { ABORT_PARSE; }
  414.         ;
  415.  
  416. input1        : '\n'
  417.           { $$ = 0; }
  418.         | '\r'
  419.           { $$ = 0; }
  420.         | ''
  421.           { $$ = 0; }
  422.         | simple_list
  423.           { $$ = $1; }
  424.         | simple_list '\n'
  425.           { $$ = $1; }
  426.         | simple_list '\r'
  427.           { $$ = $1; }
  428.         | simple_list ''
  429.           { $$ = $1; }
  430.         | simple_list END_OF_INPUT
  431.           { $$ = $1; }
  432.         ;
  433.  
  434. parse_error    : LEXICAL_ERROR
  435.           { yyerror ("parse error"); }
  436.         | error
  437.         ;
  438.  
  439. simple_list    : simple_list1 opt_sep_no_nl
  440.           {
  441.             set_stmt_print_flag ($1, $2, false);
  442.             $$ = $1;
  443.           }
  444.         ;
  445.  
  446. simple_list1    : statement
  447.           { $$ = new tree_statement_list ($1); }
  448.         | simple_list1 sep_no_nl statement
  449.           {
  450.             set_stmt_print_flag ($1, $2, false);
  451.             $1->append ($3);
  452.             $$ = $1;
  453.           }
  454.         ;
  455.  
  456. opt_list    : // empty
  457.           { $$ = new tree_statement_list (); }
  458.         | list
  459.           { $$ = $1; }
  460.         ;
  461.  
  462. list        : list1 opt_sep
  463.           {
  464.             set_stmt_print_flag ($1, $2, true);
  465.             $$ = $1;
  466.           }
  467.         ;
  468.  
  469. list1        : statement
  470.           {
  471.             lexer_flags.beginning_of_function = 0;
  472.             $$ = new tree_statement_list ($1);
  473.           }
  474.         | list1 sep statement
  475.           {
  476.             set_stmt_print_flag ($1, $2, true);
  477.             $1->append ($3);
  478.             $$ = $1;
  479.           }
  480.         ;
  481.  
  482. statement    : command
  483.           { $$ = new tree_statement ($1); }
  484.         | ans_expression
  485.           { $$ = new tree_statement ($1); }
  486.         | PLOT CLEAR
  487.           {
  488.             symbol_record *sr = lookup_by_name ("clearplot", 0);
  489.             tree_identifier *id = new tree_identifier (sr);
  490.             $$ = new tree_statement (id);
  491.           }
  492.         ;
  493.  
  494. plot_command    : PLOT plot_command1
  495.           {
  496.             if (! ($$ = make_plot_command ($1, 0, $2)))
  497.               ABORT_PARSE;
  498.           }
  499.         | PLOT ranges plot_command1
  500.           {
  501.             if (! ($$ = make_plot_command ($1, $2, $3)))
  502.               ABORT_PARSE;
  503.           }
  504.         ;
  505.  
  506. ranges        : ranges1
  507.           { $$ = new plot_limits ($1); }
  508.         | ranges1 ranges1
  509.           { $$ = new plot_limits ($1, $2); }
  510.         | ranges1 ranges1 ranges1
  511.           { $$ = new plot_limits ($1, $2, $3); }
  512.         ;
  513.  
  514. ranges1        : OPEN_BRACE expression COLON expression CLOSE_BRACE
  515.           { $$ = new plot_range ($2, $4); }
  516.         | OPEN_BRACE COLON expression CLOSE_BRACE
  517.           { $$ = new plot_range (0, $3); }
  518.         | OPEN_BRACE expression COLON CLOSE_BRACE
  519.           { $$ = new plot_range ($2, 0); }
  520.         | OPEN_BRACE COLON CLOSE_BRACE
  521.           { $$ = new plot_range (); }
  522.         | OPEN_BRACE CLOSE_BRACE
  523.           { $$ = new plot_range (); }
  524.         ;
  525.  
  526. plot_command1    : // empty
  527.           { $$ = 0; }
  528.         | plot_command2
  529.           { $$ = new subplot_list ($1); }
  530.         | plot_command1 ',' plot_command2
  531.           {
  532.             $1->append ($3);
  533.             $$ = $1;
  534.           }
  535.         ;
  536.  
  537. plot_command2    : expression
  538.           { $$ = new subplot ($1); }
  539.         | expression plot_options
  540.           { $$ = $2->set_data ($1); }
  541.         ;
  542.  
  543. plot_options    : using
  544.           { $$ = new subplot ($1, 0, 0); }
  545.         | title
  546.           { $$ = new subplot (0, $1, 0); }
  547.         | style
  548.           { $$ = new subplot (0, 0, $1); }
  549.         | using title
  550.           { $$ = new subplot ($1, $2, 0); }
  551.         | title using         
  552.           { $$ = new subplot ($2, $1, 0); }
  553.         | using style         
  554.           { $$ = new subplot ($1, 0, $2); }
  555.         | style using         
  556.           { $$ = new subplot ($2, 0, $1); }
  557.         | title style         
  558.           { $$ = new subplot (0, $1, $2); }
  559.         | style title         
  560.           { $$ = new subplot (0, $2, $1); }
  561.         | using title style     
  562.           { $$ = new subplot ($1, $2, $3); }
  563.         | using style title     
  564.           { $$ = new subplot ($1, $3, $2); }
  565.         | title using style     
  566.           { $$ = new subplot ($2, $1, $3); }
  567.         | title style using     
  568.           { $$ = new subplot ($3, $1, $2); }
  569.         | style using title     
  570.           { $$ = new subplot ($2, $3, $1); }
  571.         | style title using     
  572.           { $$ = new subplot ($3, $2, $1); }
  573.         ;
  574.  
  575. using        : using1
  576.           {
  577.             lexer_flags.in_plot_using = 0;
  578.             $$ = $1;
  579.           }
  580.         | using1 expression
  581.           {
  582.             lexer_flags.in_plot_using = 0;
  583.             $$ = $1->set_format ($2);
  584.           }
  585.         ;
  586.  
  587. using1        : USING expression
  588.           {
  589.             subplot_using *tmp = new subplot_using ();
  590.             $$ = tmp->add_qualifier ($2);
  591.           }
  592.         | using1 COLON expression
  593.           { $$ = $1->add_qualifier ($3); }
  594.         ;
  595.  
  596. title        : TITLE expression
  597.           { $$ = $2; }
  598.         ;
  599.  
  600. style        : WITH STYLE
  601.           { $$ = new subplot_style ($2->text ()); }
  602.         | WITH STYLE expression
  603.           { $$ = new subplot_style ($2->text (), $3); }
  604.         | WITH STYLE expression expression
  605.           { $$ = new subplot_style ($2->text (), $3, $4); }
  606.         ;
  607.  
  608. ans_expression    : expression
  609.           { $$ = maybe_convert_to_ans_assign ($1); }
  610.         ;
  611.  
  612. global_decl    : GLOBAL global_decl1
  613.           {
  614.             $$ = new tree_global_command ($2, $1->line (),
  615.                           $1->column ());
  616.           }
  617.         ;
  618.  
  619. global_decl1    : global_decl2
  620.           { $$ = new tree_global_init_list ($1); }
  621.         | global_decl1 optcomma global_decl2
  622.           {
  623.             $1->append ($3);
  624.             $$ = $1;
  625.           }
  626.  
  627. global_decl2    : identifier
  628.           { $$ = new tree_global ($1); }
  629.         | identifier '=' expression
  630.           {
  631.             tree_simple_assignment_expression *tmp_ass;
  632.             tmp_ass = new tree_simple_assignment_expression
  633.               ($1, $3, 0, 0, $2->line (), $2->column ());
  634.             $$ = new tree_global (tmp_ass);
  635.           }
  636.         ;
  637.  
  638. optcomma    : // empty
  639.         | ','
  640.           {
  641.             if (Vwarn_comma_in_global_decl)
  642.               warning ("comma in global declaration not\
  643.  interpreted as a command separator");
  644.           }
  645.         ;
  646.  
  647. command        : plot_command
  648.           { $$ = $1; }
  649.         | func_def
  650.           { $$ = $1; }
  651.         | global_decl
  652.           { $$ = $1; }
  653.         | switch_command
  654.           { $$ = $1; }
  655.         | if_command
  656.           { $$ = $1; }
  657.         | UNWIND opt_sep opt_list CLEANUP opt_sep opt_list END
  658.           {
  659.             if (! ($$ = make_unwind_command ($1, $3, $6, $7)))
  660.               ABORT_PARSE;
  661.           }
  662.         | TRY opt_sep opt_list CATCH opt_sep opt_list END
  663.           {
  664.             if (! ($$ = make_try_command ($1, $3, $6, $7)))
  665.               ABORT_PARSE;
  666.           }
  667.         | WHILE expression opt_sep opt_list END
  668.           {
  669.             if (! ($$ = make_while_command ($1, $2, $4, $5)))
  670.               ABORT_PARSE;
  671.           }
  672.         | FOR variable '=' expression opt_sep opt_list END
  673.           {
  674.             if (! ($$ = make_for_command ($1, $2, $4, $6, $7)))
  675.               ABORT_PARSE;
  676.           }
  677.         | FOR '[' screwed_again matrix_row SCREW_TWO '='
  678.             expression opt_sep opt_list END
  679.           {
  680.             if (! ($$ = make_for_command ($1, $4, $7, $9, $10)))
  681.               ABORT_PARSE;
  682.           }
  683.         | BREAK
  684.           {
  685.             if (! ($$ = make_break_command ($1)))
  686.               ABORT_PARSE;
  687.           }
  688.         | CONTINUE
  689.           {
  690.             if (! ($$ = make_continue_command ($1)))
  691.               ABORT_PARSE;
  692.           }
  693.         | FUNC_RET
  694.           {
  695.             if (! ($$ = make_return_command ($1)))
  696.               ABORT_PARSE;
  697.           }
  698.         ;
  699.  
  700. if_command    : IF if_cmd_list END
  701.           {
  702.             if (! ($$ = finish_if_command ($1, $2, $3)))
  703.               ABORT_PARSE;
  704.           }
  705.         ;
  706.  
  707. if_cmd_list    : if_cmd_list1
  708.           { $$ = $1; }
  709.         | if_cmd_list1 else_clause
  710.           {
  711.             $1->append ($2);
  712.             $$ = $1;
  713.           }
  714.         ;
  715.  
  716. if_cmd_list1    : expression opt_sep opt_list
  717.           { $$ = start_if_command ($1, $3); }
  718.         | if_cmd_list1 elseif_clause
  719.           {
  720.             $1->append ($2);
  721.             $$ = $1;
  722.           }
  723.         ;
  724.  
  725. elseif_clause    : ELSEIF opt_sep expression opt_sep opt_list
  726.           { $$ = make_elseif_clause ($3, $5); }
  727.         ;
  728.  
  729. else_clause    : ELSE opt_sep opt_list
  730.           { $$ = new tree_if_clause ($3); }
  731.         ;
  732.  
  733. switch_command    : SWITCH expression opt_sep case_list END
  734.           {
  735.             if (! ($$ = finish_switch_command ($1, $2, $4, $5)))
  736.               ABORT_PARSE;
  737.           }
  738.         ;
  739.  
  740. case_list    : case_list1
  741.           { $$ = $1; }
  742.         | case_list1 default_case
  743.           {
  744.             $1->append ($2);
  745.             $$ = $1;
  746.           }        
  747.         ;
  748.  
  749. case_list1    : switch_case
  750.           { $$ = new tree_switch_case_list ($1); }
  751.         | case_list1 switch_case
  752.           {
  753.             $1->append ($2);
  754.             $$ = $1;
  755.           }
  756.         ;
  757.  
  758. switch_case    : CASE opt_sep expression opt_sep list
  759.           { $$ = make_switch_case ($3, $5); }
  760.         ;
  761.  
  762. default_case    : OTHERWISE opt_sep opt_list
  763.           { $$ = new tree_switch_case ($3); }
  764.         ;
  765.  
  766. screwed_again    : // empty
  767.           { lexer_flags.maybe_screwed_again++; }
  768.         ;
  769.  
  770. expression    : simple_expr
  771.           { $$ = $1; }
  772.         | NUM '=' expression
  773.           {
  774.             yyerror ("invalid assignment to a number");
  775.             $$ = 0;
  776.             ABORT_PARSE;
  777.           }
  778.         ;
  779.  
  780. // Now that we do some simple constant folding, we have to make sure
  781. // that we get something valid back make_binary_op and make_unary_op.
  782.  
  783. simple_expr    : simple_expr1
  784.           {
  785.             if (! ($$ = $1))
  786.               ABORT_PARSE;
  787.           }
  788.         ;
  789.  
  790. simple_expr1    : NUM
  791.           { $$ = make_constant (NUM, $1); }
  792.         | IMAG_NUM
  793.           { $$ = make_constant (IMAG_NUM, $1); }
  794.         | TEXT
  795.           { $$ = make_constant (TEXT, $1); }
  796.         | '(' simple_expr ')'
  797.           {
  798.             $2->mark_in_parens ();
  799.             $$ = $2;
  800.           }
  801.         | word_list_cmd
  802.           { $$ = $1; }
  803.         | variable
  804.           { $$ = $1; }
  805.         | colon_expr
  806.           { $$ = finish_colon_expression ($1); }
  807.         | matrix
  808.           { $$ = $1; }
  809.         | '[' ']'
  810.           { $$ = new tree_constant (Matrix ()); }
  811.         | '[' ';' ']'
  812.           { $$ = new tree_constant (Matrix ()); }
  813.         | PLUS_PLUS identifier %prec UNARY
  814.           { $$ = make_prefix_op (PLUS_PLUS, $2, $1); }
  815.         | MINUS_MINUS identifier %prec UNARY
  816.           { $$ = make_prefix_op (MINUS_MINUS, $2, $1); }
  817.         | EXPR_NOT simple_expr
  818.           { $$ = make_unary_op (EXPR_NOT, $2, $1); }
  819.         | '+' simple_expr %prec UNARY
  820.           { $$ = $2; }
  821.         | '-' simple_expr %prec UNARY
  822.           { $$ = make_unary_op ('-', $2, $1); }
  823.         | variable '=' simple_expr
  824.           { $$ = make_simple_assignment ($1, $2, $3); }
  825.         | '[' screwed_again matrix_row SCREW_TWO '=' simple_expr
  826.           {
  827.             if (! ($$ = make_multi_val_ret ($3, $6, $5)))
  828.               ABORT_PARSE;
  829.           }
  830.         | identifier PLUS_PLUS
  831.           { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
  832.         | identifier MINUS_MINUS
  833.           { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
  834.         | simple_expr QUOTE
  835.           { $$ = make_unary_op (QUOTE, $1, $2); }
  836.         | simple_expr TRANSPOSE
  837.           { $$ = make_unary_op (TRANSPOSE, $1, $2); }
  838.         | simple_expr POW simple_expr
  839.           { $$ = make_binary_op (POW, $1, $2, $3); }
  840.         | simple_expr EPOW simple_expr
  841.           { $$ = make_binary_op (EPOW, $1, $2, $3); }
  842.         | simple_expr '+' simple_expr
  843.           { $$ = make_binary_op ('+', $1, $2, $3); }
  844.         | simple_expr '-' simple_expr
  845.           { $$ = make_binary_op ('-', $1, $2, $3); }
  846.         | simple_expr '*' simple_expr
  847.           { $$ = make_binary_op ('*', $1, $2, $3); }
  848.         | simple_expr '/' simple_expr
  849.           { $$ = make_binary_op ('/', $1, $2, $3); }
  850.         | simple_expr EPLUS simple_expr
  851.           { $$ = make_binary_op ('+', $1, $2, $3); }
  852.         | simple_expr EMINUS simple_expr
  853.           { $$ = make_binary_op ('-', $1, $2, $3); }
  854.         | simple_expr EMUL simple_expr
  855.           { $$ = make_binary_op (EMUL, $1, $2, $3); }
  856.         | simple_expr EDIV simple_expr
  857.           { $$ = make_binary_op (EDIV, $1, $2, $3); }
  858.         | simple_expr LEFTDIV simple_expr
  859.           { $$ = make_binary_op (LEFTDIV, $1, $2, $3); }
  860.         | simple_expr ELEFTDIV simple_expr
  861.           { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); }
  862.         | simple_expr EXPR_LT simple_expr
  863.           { $$ = make_binary_op (EXPR_LT, $1, $2, $3); }
  864.         | simple_expr EXPR_LE simple_expr
  865.           { $$ = make_binary_op (EXPR_LE, $1, $2, $3); }
  866.         | simple_expr EXPR_EQ simple_expr
  867.           { $$ = make_binary_op (EXPR_EQ, $1, $2, $3); }
  868.         | simple_expr EXPR_GE simple_expr
  869.           { $$ = make_binary_op (EXPR_GE, $1, $2, $3); }
  870.         | simple_expr EXPR_GT simple_expr
  871.           { $$ = make_binary_op (EXPR_GT, $1, $2, $3); }
  872.         | simple_expr EXPR_NE simple_expr
  873.           { $$ = make_binary_op (EXPR_NE, $1, $2, $3); }
  874.         | simple_expr EXPR_AND simple_expr
  875.           { $$ = make_binary_op (EXPR_AND, $1, $2, $3); }
  876.         | simple_expr EXPR_OR simple_expr
  877.           { $$ = make_binary_op (EXPR_OR, $1, $2, $3); }
  878.         | simple_expr EXPR_AND_AND simple_expr
  879.           { $$ = make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
  880.         | simple_expr EXPR_OR_OR simple_expr
  881.           { $$ = make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
  882.         ;
  883.  
  884. colon_expr    : simple_expr ':' simple_expr
  885.           {
  886.             $$ = new tree_colon_expression
  887.               ($1, $3, $2->line (), $2->column ());
  888.           }
  889.         | colon_expr ':' simple_expr
  890.           {
  891.             if (! ($$ = $1->chain ($3)))
  892.               ABORT_PARSE;
  893.           }
  894.         ;
  895.  
  896. word_list_cmd    : identifier word_list
  897.           {
  898.             $$ = new tree_index_expression
  899.               ($1, $2, $1->line (), $1->column ());
  900.           }
  901.         ;
  902.  
  903. word_list    : TEXT
  904.           {
  905.             tree_constant *tmp = make_constant (TEXT, $1);
  906.             $$ = new tree_argument_list (tmp);
  907.           }
  908.         | word_list TEXT
  909.           {
  910.             tree_constant *tmp = make_constant (TEXT, $2);
  911.             $1->append (tmp);
  912.             $$ = $1;
  913.           }
  914.         ;
  915.  
  916. // This is truly disgusting.
  917.  
  918. g_symtab    : // empty
  919.           { curr_sym_tab = global_sym_tab; }
  920.         ;
  921.  
  922. in_return_list    : // empty
  923.           { lexer_flags.looking_at_return_list = 1; }
  924.         ;
  925.  
  926. local_symtab    : // empty
  927.           { curr_sym_tab = tmp_local_sym_tab; }
  928.         ;
  929.  
  930. safe        : // empty
  931.           { lexer_flags.maybe_screwed = 0; }
  932.         ;
  933.  
  934. are_we_screwed    : // empty
  935.           { lexer_flags.maybe_screwed = 1; }
  936.         ;
  937.  
  938. func_def    : FCN g_symtab are_we_screwed func_def1
  939.           {
  940.             curr_sym_tab = top_level_sym_tab;
  941.             lexer_flags.defining_func = 0;
  942.             $$ = 0;
  943.           }
  944.         | FCN g_symtab are_we_screwed func_def2
  945.           {
  946.             curr_sym_tab = top_level_sym_tab;
  947.             lexer_flags.defining_func = 0;
  948.             $$ = 0;
  949.           }
  950.         ;
  951.  
  952. func_def1    : SCREW safe g_symtab '=' func_def2
  953.           { $$ = finish_function_def ($1, $5); }
  954.         | return_list g_symtab '=' func_def2
  955.           { $$ = finish_function_def ($1, $4); }
  956.         ;
  957.  
  958. return_list_x    : '[' safe local_symtab in_return_list
  959.         ;
  960.  
  961. return_list    : return_list_x ']'
  962.           {
  963.             lexer_flags.looking_at_return_list = 0;
  964.             $$ = new tree_parameter_list ();
  965.           }
  966.         | return_list_x ELLIPSIS ']'
  967.           {
  968.             lexer_flags.looking_at_return_list = 0;
  969.             tree_parameter_list *tmp = new tree_parameter_list ();
  970.             tmp->mark_varargs_only ();
  971.             $$ = tmp;
  972.           }
  973.         | return_list1 ']'
  974.           {
  975.             lexer_flags.looking_at_return_list = 0;
  976.             $$ = $1;
  977.           }
  978.         | return_list1 ',' ELLIPSIS ']'
  979.           {
  980.             lexer_flags.looking_at_return_list = 0;
  981.             $1->mark_varargs ();
  982.             $$ = $1;
  983.           }
  984.         ;
  985.  
  986. return_list1    : return_list_x identifier
  987.           { $$ = new tree_parameter_list ($2); }
  988.         | return_list_x error
  989.           {
  990.             yyerror ("invalid function return list");
  991.             $$ = 0;
  992.             ABORT_PARSE;
  993.           }
  994.         | return_list1 ',' identifier
  995.           {
  996.             $1->append ($3);
  997.             $$ = $1;
  998.           }
  999.         ;
  1000.  
  1001. func_def2    : identifier safe local_symtab func_def3
  1002.           {
  1003.             if (! ($$ = frob_function_def ($1, $4)))
  1004.               ABORT_PARSE;
  1005.           }
  1006.         ;
  1007.  
  1008. func_def3    : param_list opt_sep opt_list fcn_end_or_eof
  1009.           { $$ = start_function_def ($1, $3); }
  1010.         | opt_sep opt_list fcn_end_or_eof
  1011.           { $$ = start_function_def (0, $2); }
  1012.         ;
  1013.  
  1014. fcn_end_or_eof    : END
  1015.           {
  1016.             if (check_end ($1, token::function_end))
  1017.               ABORT_PARSE;
  1018.  
  1019.             if (reading_fcn_file)
  1020.               check_for_garbage_after_fcn_def ();
  1021.           }
  1022.         | END_OF_INPUT
  1023.           {
  1024.             if (! (reading_fcn_file || reading_script_file))
  1025.               YYABORT;
  1026.           }
  1027.         ;
  1028.  
  1029. indirect_ref    : indirect_ref1
  1030.           {
  1031.             lexer_flags.looking_at_indirect_ref = 0;
  1032.             $$ = $1;
  1033.           }
  1034.  
  1035. indirect_ref1    : identifier
  1036.           {
  1037.             $$ = new tree_indirect_ref ($1, $1->line (),
  1038.                         $1->column ());
  1039.           }
  1040.         | indirect_ref1 '.'
  1041.             { lexer_flags.looking_at_indirect_ref = 1; } TEXT_ID
  1042.           { $$ = new tree_indirect_ref ($1, $4->text ()); }
  1043.         ;
  1044.  
  1045. variable    : indirect_ref
  1046.           { $$ = make_index_expression ($1, 0); }
  1047.         | indirect_ref '(' ')'
  1048.           { $$ = make_index_expression ($1, 0); }
  1049.         | indirect_ref '(' arg_list ')'
  1050.           { $$ = make_index_expression ($1, $3); }
  1051.         | indirect_ref '['
  1052.           {
  1053.             yyerror ("use `(\' and `)\' as index operators, not\
  1054.  `[\' and `]\'"); 
  1055.             $$ = 0;
  1056.             ABORT_PARSE;
  1057.           }
  1058.         ;
  1059.  
  1060. param_list_beg    : '('
  1061.           { lexer_flags.looking_at_parameter_list = 1; }
  1062.         ;
  1063.  
  1064. param_list_end    : ')'
  1065.           { lexer_flags.looking_at_parameter_list = 0; }
  1066.         ;
  1067.  
  1068. param_list    : param_list_beg param_list_end
  1069.           {
  1070.             lexer_flags.quote_is_transpose = 0;
  1071.             $$ = 0;
  1072.           }
  1073.         | param_list_beg ELLIPSIS param_list_end
  1074.           {
  1075.             lexer_flags.quote_is_transpose = 0;
  1076.             tree_parameter_list *tmp = new tree_parameter_list ();
  1077.             tmp->mark_varargs_only ();
  1078.             $$ = tmp;
  1079.           }
  1080.         | param_list1 param_list_end
  1081.           {
  1082.             lexer_flags.looking_at_parameter_list = 0;
  1083.             lexer_flags.quote_is_transpose = 0;
  1084.             $1->mark_as_formal_parameters ();
  1085.             $$ = $1;
  1086.           }
  1087.         | param_list1 ',' ELLIPSIS param_list_end
  1088.           {
  1089.             lexer_flags.looking_at_parameter_list = 0;
  1090.             lexer_flags.quote_is_transpose = 0;
  1091.             $1->mark_as_formal_parameters ();
  1092.             $1->mark_varargs ();
  1093.             $$ = $1;
  1094.           }
  1095.         ;
  1096.  
  1097. param_list1    : param_list_beg identifier
  1098.           { $$ = new tree_parameter_list ($2); }
  1099.         | param_list1 ',' identifier
  1100.           {
  1101.             $1->append ($3);
  1102.             $$ = $1;
  1103.           }
  1104.         | param_list_beg error
  1105.           {
  1106.             yyerror ("invalid parameter list");
  1107.             $$ = 0;
  1108.             ABORT_PARSE;
  1109.           }
  1110.         | param_list1 ',' error
  1111.           {
  1112.             yyerror ("invalid parameter list");
  1113.             $$ = 0;
  1114.             ABORT_PARSE;
  1115.           }
  1116.         ;
  1117.  
  1118. identifier    : NAME
  1119.           {
  1120.             $$ = new tree_identifier
  1121.               ($1->sym_rec (), $1->line (), $1->column ());
  1122.           }
  1123.         ;
  1124.  
  1125. arg_list    : ':'
  1126.           {
  1127.             tree_constant *colon =
  1128.               new tree_constant (tree_constant::magic_colon_t);
  1129.             $$ = new tree_argument_list (colon);
  1130.           }
  1131.         | expression
  1132.           { $$ = new tree_argument_list ($1); }
  1133.         | ALL_VA_ARGS
  1134.           {
  1135.             tree_constant *all_va_args =
  1136.               new tree_constant (tree_constant::all_va_args_t);
  1137.             $$ = new tree_argument_list (all_va_args);
  1138.           }
  1139.         | arg_list ',' ':'
  1140.           {
  1141.             tree_constant *colon =
  1142.               new tree_constant (tree_constant::magic_colon_t);
  1143.             $1->append (colon);
  1144.             $$ = $1;
  1145.           }
  1146.         | arg_list ',' expression
  1147.           {
  1148.             $1->append ($3);
  1149.             $$ = $1;
  1150.           }
  1151.         | arg_list ',' ALL_VA_ARGS
  1152.           {
  1153.             tree_constant *all_va_args =
  1154.               new tree_constant (tree_constant::all_va_args_t);
  1155.             $1->append (all_va_args);
  1156.             $$ = $1;
  1157.           }
  1158.         ;
  1159.  
  1160. matrix        : '[' screwed_again rows ']'
  1161.           { $$ = finish_matrix ($3); }
  1162.         ;
  1163.  
  1164. rows        : rows1
  1165.           { $$ = $1; }
  1166.         | rows1 ';'    // Ignore trailing semicolon.
  1167.           { $$ = $1; }
  1168.         ;
  1169.  
  1170. rows1        : matrix_row
  1171.           { $$ = new tree_matrix ($1); }
  1172.         | rows1 ';' matrix_row
  1173.           {
  1174.             $1->append ($3);
  1175.             $$ = $1;
  1176.           }
  1177.         ;
  1178.  
  1179. matrix_row    : matrix_row1
  1180.           { $$ = $1; }
  1181.         | matrix_row1 ','    // Ignore trailing comma.
  1182.           { $$ = $1; }
  1183.         ;
  1184.  
  1185. matrix_row1    : expression        // First element on row.
  1186.           { $$ = new tree_matrix_row ($1); }
  1187.         | matrix_row1 ',' expression
  1188.           {
  1189.             $1->append ($3);
  1190.             $$ = $1;
  1191.           }
  1192.         ;
  1193.  
  1194. sep_no_nl    : ','
  1195.           { $$ = ','; }
  1196.         | ';'
  1197.           { $$ = ';'; }
  1198.         | sep_no_nl ','
  1199.           { $$ = $1; }
  1200.         | sep_no_nl ';'
  1201.           { $$ = $1; }
  1202.         ;
  1203.  
  1204. opt_sep_no_nl    : // empty
  1205.           { $$ = 0; }
  1206.         | sep_no_nl
  1207.           { $$ = $1; }
  1208.         ;
  1209.  
  1210. sep        : ','
  1211.           { $$ = ','; }
  1212.         | ';'
  1213.           { $$ = ';'; }
  1214.         | '\n'
  1215.           { $$ = '\n'; }
  1216.         | '\r'
  1217.           { $$ = '\r'; }
  1218.         | sep ','
  1219.           { $$ = $1; }
  1220.         | sep ';'
  1221.           { $$ = $1; }
  1222.         | sep '\n'
  1223.           { $$ = $1; }
  1224.         | sep '\r'
  1225.           { $$ = $1; }
  1226.         ;
  1227.  
  1228. opt_sep        : // empty
  1229.           { $$ = 0; }
  1230.         | sep
  1231.           { $$ = $1; }
  1232.         ;
  1233.  
  1234. %%
  1235.  
  1236. // Generic error messages.
  1237.  
  1238. static void
  1239. yyerror (char *s)
  1240. {
  1241.   int err_col = current_input_column - 1;
  1242.  
  1243.   ostrstream output_buf;
  1244.  
  1245.   if (reading_fcn_file || reading_script_file)
  1246.     output_buf << "parse error near line " << input_line_number
  1247.            << " of file " << curr_fcn_file_full_name;
  1248.   else
  1249.     output_buf << "parse error:";
  1250.  
  1251.   if (s && strcmp (s, "parse error") != 0)
  1252.     output_buf << "\n\n  " << s;
  1253.  
  1254.   output_buf << "\n\n";
  1255.  
  1256.   if (! current_input_line.empty ())
  1257.     {
  1258.       size_t len = current_input_line.length ();
  1259.  
  1260.       if (current_input_line[len-1] == '\n')
  1261.         current_input_line.resize (len-1);
  1262.  
  1263. // Print the line, maybe with a pointer near the error token.
  1264.  
  1265.       output_buf << ">>> " << current_input_line << "\n";
  1266.  
  1267.       if (err_col == 0)
  1268.     err_col = len;
  1269.  
  1270.       for (int i = 0; i < err_col + 3; i++)
  1271.     output_buf << " ";
  1272.  
  1273.       output_buf << "^";
  1274.     }
  1275.  
  1276.   output_buf << "\n" << ends;
  1277.  
  1278.   char *msg = output_buf.str ();
  1279.  
  1280.   parse_error ("%s", msg);
  1281.  
  1282.   delete [] msg;
  1283. }
  1284.  
  1285. // Error mesages for mismatched end tokens.
  1286.  
  1287. static void
  1288. end_error (char *type, token::end_tok_type ettype, int l, int c)
  1289. {
  1290.   static char *fmt = "`%s' command matched by `%s' near line %d column %d";
  1291.  
  1292.   switch (ettype)
  1293.     {
  1294.     case token::simple_end:
  1295.       error (fmt, type, "end", l, c);
  1296.       break;
  1297.  
  1298.     case token::for_end:
  1299.       error (fmt, type, "endfor", l, c);
  1300.       break;
  1301.  
  1302.     case token::function_end:
  1303.       error (fmt, type, "endfunction", l, c);
  1304.       break;
  1305.  
  1306.     case token::if_end:
  1307.       error (fmt, type, "endif", l, c);
  1308.       break;
  1309.  
  1310.     case token::while_end:
  1311.       error (fmt, type, "endwhile", l, c); 
  1312.       break;
  1313.  
  1314.     case token::unwind_protect_end:
  1315.       error (fmt, type, "end_unwind_protect", l, c); 
  1316.       break;
  1317.  
  1318.     default:
  1319.       panic_impossible ();
  1320.       break;
  1321.     }
  1322. }
  1323.  
  1324. // Check to see that end tokens are properly matched.
  1325.  
  1326. static int
  1327. check_end (token *tok, token::end_tok_type expected)
  1328. {
  1329.   token::end_tok_type ettype = tok->ettype ();
  1330.   if (ettype != expected && ettype != token::simple_end)
  1331.     {
  1332.       yyerror ("parse error");
  1333.  
  1334.       int l = tok->line ();
  1335.       int c = tok->column ();
  1336.  
  1337.       switch (expected)
  1338.     {
  1339.     case token::for_end:
  1340.       end_error ("for", ettype, l, c);
  1341.       break;
  1342.  
  1343.     case token::function_end:
  1344.       end_error ("function", ettype, l, c);
  1345.       break;
  1346.  
  1347.     case token::if_end:
  1348.       end_error ("if", ettype, l, c);
  1349.       break;
  1350.  
  1351.     case token::try_catch_end:
  1352.       end_error ("try", ettype, l, c);
  1353.       break;
  1354.  
  1355.     case token::switch_end:
  1356.       end_error ("switch", ettype, l, c);
  1357.       break;
  1358.  
  1359.     case token::unwind_protect_end:
  1360.       end_error ("unwind_protect", ettype, l, c);
  1361.       break;
  1362.  
  1363.     case token::while_end:
  1364.       end_error ("while", ettype, l, c);
  1365.       break;
  1366.  
  1367.     default:
  1368.       panic_impossible ();
  1369.       break;
  1370.     }
  1371.       return 1;
  1372.     }
  1373.   else
  1374.     return 0;
  1375. }
  1376.  
  1377. // Try to figure out early if an expression should become an
  1378. // assignment to the built-in variable ans.
  1379. //
  1380. // Need to make sure that the expression is not already an identifier
  1381. // that has a name, or an assignment expression.
  1382. //
  1383. // Note that an expression can not be just an identifier now -- it
  1384. // must at least be an index expression (see the definition of the
  1385. // non-terminal variable above).
  1386.  
  1387. static tree_expression *
  1388. maybe_convert_to_ans_assign (tree_expression *expr)
  1389. {
  1390.   if (expr->is_index_expression ())
  1391.     {
  1392.       expr->mark_for_possible_ans_assign ();
  1393.       return expr;
  1394.     }
  1395.   else if (expr->is_assignment_expression ()
  1396.        || expr->is_prefix_expression ())
  1397.     {
  1398.       return expr;
  1399.     }
  1400.   else
  1401.     {
  1402.       // XXX FIXME XXX -- making ans_id static, passing its address to
  1403.       // tree_simple_assignment_expression along with a flag to not
  1404.       // delete it seems to create a memory leak.  Hmm.
  1405.  
  1406.       static symbol_record *sr = global_sym_tab->lookup ("ans", 1, 0);
  1407.       tree_identifier *ans_id = new tree_identifier (sr);
  1408.  
  1409.       int l = expr->line ();
  1410.       int c = expr->column ();
  1411.  
  1412.       return new tree_simple_assignment_expression (ans_id, expr, 0, 1, l, c);
  1413.     }
  1414. }
  1415.  
  1416. // Maybe print a warning if an assignment expression is used as the
  1417. // test in a logical expression.
  1418.  
  1419. static void
  1420. maybe_warn_assign_as_truth_value (tree_expression *expr)
  1421. {
  1422.   if (Vwarn_assign_as_truth_value
  1423.       && expr->is_assignment_expression ()
  1424.       && expr->is_in_parens () < 2)
  1425.     {
  1426.       warning ("suggest parenthesis around assignment used as truth value");
  1427.     }
  1428. }
  1429.  
  1430. // Maybe print a warning about switch labels that aren't constants.
  1431.  
  1432. static void
  1433. maybe_warn_variable_switch_label (tree_expression *expr)
  1434. {
  1435.   if (Vwarn_variable_switch_label && ! expr->is_constant ())
  1436.     {
  1437.       warning ("variable switch label");
  1438.     }
  1439. }
  1440.  
  1441. // Create a plot command.
  1442.  
  1443. static tree_plot_command *
  1444. make_plot_command (token *tok, plot_limits *range, subplot_list *list)
  1445. {
  1446.   if (range)
  1447.     {
  1448.       if (tok->pttype () == token::replot)
  1449.     {
  1450.       yyerror ("cannot specify new ranges with replot");
  1451.       return 0;
  1452.     }
  1453.     }
  1454.   else if (! list && tok->pttype () != token::replot)
  1455.     {
  1456.       yyerror ("must have something to plot");
  1457.       return 0;
  1458.     }
  1459.  
  1460.   lexer_flags.plotting = 0;
  1461.   lexer_flags.past_plot_range = 0;
  1462.   lexer_flags.in_plot_range = 0;
  1463.   lexer_flags.in_plot_using = 0;
  1464.   lexer_flags.in_plot_style = 0;
  1465.   
  1466.   return new tree_plot_command (list, range, tok->pttype ());
  1467. }
  1468.  
  1469. static tree_expression *
  1470. fold (tree_binary_expression *e)
  1471. {
  1472.   tree_expression *retval = 0;
  1473.  
  1474.   tree_expression *op1 = e->lhs ();
  1475.   tree_expression *op2 = e->rhs ();
  1476.  
  1477.   if (op1->is_constant () && op2->is_constant ())
  1478.     {
  1479.       octave_value tmp = e->eval (0);
  1480.  
  1481.       if (! error_state)
  1482.     {
  1483.       tree_constant *tc_retval = new tree_constant (tmp);
  1484.  
  1485.       ostrstream buf;
  1486.  
  1487.       tree_print_code tpc (buf);
  1488.  
  1489.       e->accept (tpc);
  1490.  
  1491.       buf << ends;
  1492.  
  1493.       char *s = buf.str ();
  1494.  
  1495.       tc_retval->stash_original_text (s);
  1496.  
  1497.       delete [] s;
  1498.  
  1499.       delete e;
  1500.  
  1501.       retval = tc_retval;
  1502.     }
  1503.       else
  1504.     delete e;
  1505.     }
  1506.   else
  1507.     retval = e;
  1508.  
  1509.   return retval;
  1510. }
  1511.  
  1512. static tree_expression *
  1513. fold (tree_unary_expression *e)
  1514. {
  1515.   tree_expression *retval = 0;
  1516.  
  1517.   tree_expression *op1 = e->operand ();
  1518.  
  1519.   if (op1->is_constant ())
  1520.     {
  1521.       octave_value tmp = e->eval (0);
  1522.  
  1523.       if (! error_state)
  1524.     {
  1525.       tree_constant *tc_retval = new tree_constant (tmp);
  1526.  
  1527.       ostrstream buf;
  1528.  
  1529.       tree_print_code tpc (buf);
  1530.  
  1531.       e->accept (tpc);
  1532.  
  1533.       buf << ends;
  1534.  
  1535.       char *s = buf.str ();
  1536.  
  1537.       tc_retval->stash_original_text (s);
  1538.  
  1539.       delete [] s;
  1540.  
  1541.       delete e;
  1542.  
  1543.       retval = tc_retval;
  1544.     }
  1545.       else
  1546.     delete e;
  1547.     }
  1548.   else
  1549.     retval = e;
  1550.  
  1551.   return retval;
  1552. }
  1553.  
  1554. // Finish building a range.
  1555.  
  1556. static tree_expression *
  1557. finish_colon_expression (tree_colon_expression *e)
  1558. {
  1559.   tree_expression *retval = 0;
  1560.  
  1561.   tree_expression *base = e->base ();
  1562.   tree_expression *limit = e->limit ();
  1563.   tree_expression *incr = e->increment ();
  1564.  
  1565.   if (base->is_constant () && limit->is_constant ()
  1566.       && (! incr || (incr && incr->is_constant ())))
  1567.     {
  1568.       octave_value tmp = e->eval (0);
  1569.  
  1570.       if (! error_state)
  1571.     {
  1572.       tree_constant *tc_retval = new tree_constant (tmp);
  1573.  
  1574.       ostrstream buf;
  1575.  
  1576.       tree_print_code tpc (buf);
  1577.  
  1578.       e->accept (tpc);
  1579.  
  1580.       buf << ends;
  1581.  
  1582.       char *s = buf.str ();
  1583.  
  1584.       tc_retval->stash_original_text (s);
  1585.  
  1586.       delete [] s;
  1587.  
  1588.       delete e;
  1589.  
  1590.       retval = tc_retval;
  1591.     }
  1592.       else
  1593.     delete e;
  1594.     }
  1595.   else
  1596.     retval = e;
  1597.  
  1598.   return retval;
  1599. }
  1600.  
  1601. // Make a constant.
  1602.  
  1603. static tree_constant *
  1604. make_constant (int op, token *tok_val)
  1605. {
  1606.   int l = tok_val->line ();
  1607.   int c = tok_val->column ();
  1608.  
  1609.   tree_constant *retval;
  1610.  
  1611.   switch (op)
  1612.     {
  1613.     case NUM:
  1614.       {
  1615.     retval = new tree_constant (tok_val->number (), l, c);
  1616.     retval->stash_original_text (tok_val->text_rep ());
  1617.       }
  1618.       break;
  1619.  
  1620.     case IMAG_NUM:
  1621.       {
  1622.     Complex C (0.0, tok_val->number ());
  1623.     retval = new tree_constant (C, l, c);
  1624.     retval->stash_original_text (tok_val->text_rep ());
  1625.       }
  1626.       break;
  1627.  
  1628.     case TEXT:
  1629.       retval = new tree_constant (tok_val->text (), l, c);
  1630.       break;
  1631.  
  1632.     default:
  1633.       panic_impossible ();
  1634.       break;
  1635.     }
  1636.  
  1637.   return retval;
  1638. }
  1639.  
  1640. // Build a binary expression.
  1641.  
  1642. static tree_expression *
  1643. make_binary_op (int op, tree_expression *op1, token *tok_val,
  1644.         tree_expression *op2)
  1645. {
  1646.   tree_binary_expression::type t;
  1647.  
  1648.   switch (op)
  1649.     {
  1650.     case POW:
  1651.       t = tree_binary_expression::power;
  1652.       break;
  1653.  
  1654.     case EPOW:
  1655.       t = tree_binary_expression::elem_pow;
  1656.       break;
  1657.  
  1658.     case '+':
  1659.       t = tree_binary_expression::add;
  1660.       break;
  1661.  
  1662.     case '-':
  1663.       t = tree_binary_expression::subtract;
  1664.       break;
  1665.  
  1666.     case '*':
  1667.       t = tree_binary_expression::multiply;
  1668.       break;
  1669.  
  1670.     case '/':
  1671.       t = tree_binary_expression::divide;
  1672.       break;
  1673.  
  1674.     case EMUL:
  1675.       t = tree_binary_expression::el_mul;
  1676.       break;
  1677.  
  1678.     case EDIV:
  1679.       t = tree_binary_expression::el_div;
  1680.       break;
  1681.  
  1682.     case LEFTDIV:
  1683.       t = tree_binary_expression::leftdiv;
  1684.       break;
  1685.  
  1686.     case ELEFTDIV:
  1687.       t = tree_binary_expression::el_leftdiv;
  1688.       break;
  1689.  
  1690.     case EXPR_LT:
  1691.       t = tree_binary_expression::cmp_lt;
  1692.       break;
  1693.  
  1694.     case EXPR_LE:
  1695.       t = tree_binary_expression::cmp_le;
  1696.       break;
  1697.  
  1698.     case EXPR_EQ:
  1699.       t = tree_binary_expression::cmp_eq;
  1700.       break;
  1701.  
  1702.     case EXPR_GE:
  1703.       t = tree_binary_expression::cmp_ge;
  1704.       break;
  1705.  
  1706.     case EXPR_GT:
  1707.       t = tree_binary_expression::cmp_gt;
  1708.       break;
  1709.  
  1710.     case EXPR_NE:
  1711.       t = tree_binary_expression::cmp_ne;
  1712.       break;
  1713.  
  1714.     case EXPR_AND:
  1715.       t = tree_binary_expression::and;
  1716.       break;
  1717.  
  1718.     case EXPR_OR:
  1719.       t = tree_binary_expression::or;
  1720.       break;
  1721.  
  1722.     default:
  1723.       panic_impossible ();
  1724.       break;
  1725.     }
  1726.  
  1727.   int l = tok_val->line ();
  1728.   int c = tok_val->column ();
  1729.  
  1730.   tree_binary_expression *e
  1731.     = new tree_binary_expression (op1, op2, l, c, t);
  1732.  
  1733.   return fold (e);
  1734. }
  1735.  
  1736. // Build a boolean expression.
  1737.  
  1738. static tree_expression *
  1739. make_boolean_op (int op, tree_expression *op1, token *tok_val,
  1740.          tree_expression *op2)
  1741. {
  1742.   tree_boolean_expression::type t;
  1743.  
  1744.   switch (op)
  1745.     {
  1746.     case EXPR_AND_AND:
  1747.       t = tree_boolean_expression::and;
  1748.       break;
  1749.  
  1750.     case EXPR_OR_OR:
  1751.       t = tree_boolean_expression::or;
  1752.       break;
  1753.  
  1754.     default:
  1755.       panic_impossible ();
  1756.       break;
  1757.     }
  1758.  
  1759.   int l = tok_val->line ();
  1760.   int c = tok_val->column ();
  1761.  
  1762.   tree_boolean_expression *e
  1763.     = new tree_boolean_expression (op1, op2, l, c, t);
  1764.  
  1765.   return fold (e);
  1766. }
  1767.  
  1768. // Build a prefix expression.
  1769.  
  1770. static tree_expression *
  1771. make_prefix_op (int op, tree_identifier *op1, token *tok_val)
  1772. {
  1773.   tree_prefix_expression::type t;
  1774.  
  1775.   switch (op)
  1776.     {
  1777.     case PLUS_PLUS:
  1778.       t = tree_prefix_expression::increment;
  1779.       break;
  1780.  
  1781.     case MINUS_MINUS:
  1782.       t = tree_prefix_expression::decrement;
  1783.       break;
  1784.  
  1785.     default:
  1786.       panic_impossible ();
  1787.       break;
  1788.     }
  1789.  
  1790.   int l = tok_val->line ();
  1791.   int c = tok_val->column ();
  1792.  
  1793.   return new tree_prefix_expression (op1, l, c, t);
  1794. }
  1795.  
  1796. // Build a postfix expression.
  1797.  
  1798. static tree_expression *
  1799. make_postfix_op (int op, tree_identifier *op1, token *tok_val)
  1800. {
  1801.   tree_postfix_expression::type t;
  1802.  
  1803.   switch (op)
  1804.     {
  1805.     case PLUS_PLUS:
  1806.       t = tree_postfix_expression::increment;
  1807.       break;
  1808.  
  1809.     case MINUS_MINUS:
  1810.       t = tree_postfix_expression::decrement;
  1811.       break;
  1812.  
  1813.     default:
  1814.       panic_impossible ();
  1815.       break;
  1816.     }
  1817.  
  1818.   int l = tok_val->line ();
  1819.   int c = tok_val->column ();
  1820.  
  1821.   return new tree_postfix_expression (op1, l, c, t);
  1822. }
  1823.  
  1824. // Build a unary expression.
  1825.  
  1826. static tree_expression *
  1827. make_unary_op (int op, tree_expression *op1, token *tok_val)
  1828. {
  1829.   tree_unary_expression::type t;
  1830.  
  1831.   switch (op)
  1832.     {
  1833.     case QUOTE:
  1834.       t = tree_unary_expression::hermitian;
  1835.       break;
  1836.  
  1837.     case TRANSPOSE:
  1838.       t = tree_unary_expression::transpose;
  1839.       break;
  1840.  
  1841.     case EXPR_NOT:
  1842.       t = tree_unary_expression::not;
  1843.       break;
  1844.  
  1845.     case '-':
  1846.       t = tree_unary_expression::uminus;
  1847.       break;
  1848.  
  1849.     default:
  1850.       panic_impossible ();
  1851.       break;
  1852.     }
  1853.  
  1854.   int l = tok_val->line ();
  1855.   int c = tok_val->column ();
  1856.  
  1857.   tree_unary_expression *e
  1858.     = new tree_unary_expression (op1, l, c, t);
  1859.  
  1860.   return fold (e);
  1861. }
  1862.  
  1863. // Build an unwind-protect command.
  1864.  
  1865. static tree_command *
  1866. make_unwind_command (token *unwind_tok, tree_statement_list *body,
  1867.              tree_statement_list *cleanup, token *end_tok)
  1868. {
  1869.   tree_command *retval = 0;
  1870.  
  1871.   if (! check_end (end_tok, token::unwind_protect_end))
  1872.     {
  1873.       int l = unwind_tok->line ();
  1874.       int c = unwind_tok->column ();
  1875.  
  1876.       retval = new tree_unwind_protect_command (body, cleanup, l, c);
  1877.     }
  1878.  
  1879.   return retval;
  1880. }
  1881.  
  1882. // Build a try-catch command.
  1883.  
  1884. static tree_command *
  1885. make_try_command (token *try_tok, tree_statement_list *body,
  1886.           tree_statement_list *cleanup, token *end_tok)
  1887. {
  1888.   tree_command *retval = 0;
  1889.  
  1890.   if (! check_end (end_tok, token::try_catch_end))
  1891.     {
  1892.       int l = try_tok->line ();
  1893.       int c = try_tok->column ();
  1894.  
  1895.       retval = new tree_try_catch_command (body, cleanup, l, c);
  1896.     }
  1897.  
  1898.   return retval;
  1899. }
  1900.  
  1901. // Build a while command.
  1902.  
  1903. static tree_command *
  1904. make_while_command (token *while_tok, tree_expression *expr,
  1905.             tree_statement_list *body, token *end_tok)
  1906. {
  1907.   tree_command *retval = 0;
  1908.  
  1909.   maybe_warn_assign_as_truth_value (expr);
  1910.  
  1911.   if (! check_end (end_tok, token::while_end))
  1912.     {
  1913.       lexer_flags.looping--;
  1914.  
  1915.       int l = while_tok->line ();
  1916.       int c = while_tok->column ();
  1917.  
  1918.       retval = new tree_while_command (expr, body, l, c);
  1919.     }
  1920.  
  1921.   return retval;
  1922. }
  1923.  
  1924. // Build a for command.
  1925.  
  1926. static tree_command *
  1927. make_for_command (token *for_tok, tree_index_expression *var,
  1928.           tree_expression *expr, tree_statement_list *body,
  1929.           token *end_tok)
  1930. {
  1931.   tree_command *retval = 0;
  1932.  
  1933.   if (! check_end (end_tok, token::for_end))
  1934.     {
  1935.       lexer_flags.looping--;
  1936.  
  1937.       int l = for_tok->line ();
  1938.       int c = for_tok->column ();
  1939.  
  1940.       retval = new tree_for_command (var, expr, body, l, c);
  1941.     }
  1942.  
  1943.   return retval;
  1944. }
  1945.  
  1946. // Build a for command a different way.
  1947.  
  1948. static tree_command *
  1949. make_for_command (token *for_tok, tree_matrix_row *mr,
  1950.           tree_expression *expr, tree_statement_list *body,
  1951.           token *end_tok)
  1952. {
  1953.   tree_command *retval = 0;
  1954.  
  1955.   if (! check_end (end_tok, token::for_end))
  1956.     {
  1957.       lexer_flags.looping--;
  1958.  
  1959.       tree_return_list *id_list = mr->to_return_list ();
  1960.  
  1961.       int l = for_tok->line ();
  1962.       int c = for_tok->column ();
  1963.  
  1964.       retval = new tree_for_command (id_list, expr, body, l, c);
  1965.     }
  1966.  
  1967.   return retval;
  1968. }
  1969.  
  1970. // Build a break command.
  1971.  
  1972. static tree_command *
  1973. make_break_command (token *break_tok)
  1974. {
  1975.   tree_command *retval = 0;
  1976.  
  1977.   int l = break_tok->line ();
  1978.   int c = break_tok->column ();
  1979.  
  1980.   if (lexer_flags.looping || lexer_flags.defining_func || reading_script_file)
  1981.     retval = new tree_break_command (l, c);
  1982.   else
  1983.     retval = new tree_no_op_command ("break", l, c);
  1984.  
  1985.   return retval;
  1986. }
  1987.  
  1988. // Build a continue command.
  1989.  
  1990. static tree_command *
  1991. make_continue_command (token *continue_tok)
  1992. {
  1993.   tree_command *retval = 0;
  1994.  
  1995.   int l = continue_tok->line ();
  1996.   int c = continue_tok->column ();
  1997.  
  1998.   if (lexer_flags.looping)
  1999.     retval = new tree_continue_command (l, c);
  2000.   else
  2001.     retval = new tree_no_op_command ("continue", l, c);
  2002.  
  2003.   return retval;
  2004. }
  2005.  
  2006. // Build a return command.
  2007.  
  2008. static tree_command *
  2009. make_return_command (token *return_tok)
  2010. {
  2011.   tree_command *retval = 0;
  2012.  
  2013.   int l = return_tok->line ();
  2014.   int c = return_tok->column ();
  2015.  
  2016.   if (lexer_flags.defining_func || reading_script_file)
  2017.     retval = new tree_return_command (l, c);
  2018.   else
  2019.     retval = new tree_no_op_command ("return", l, c);
  2020.  
  2021.   return retval;
  2022. }
  2023.  
  2024. // Start an if command.
  2025.  
  2026. static tree_if_command_list *
  2027. start_if_command (tree_expression *expr, tree_statement_list *list)
  2028. {
  2029.   maybe_warn_assign_as_truth_value (expr);
  2030.  
  2031.   tree_if_clause *t = new tree_if_clause (expr, list);
  2032.  
  2033.   return new tree_if_command_list (t);
  2034. }
  2035.  
  2036. // Finish an if command.
  2037.  
  2038. static tree_if_command *
  2039. finish_if_command (token *if_tok, tree_if_command_list *list,
  2040.            token *end_tok)
  2041. {
  2042.   tree_if_command *retval = 0;
  2043.  
  2044.   if (! check_end (end_tok, token::if_end))
  2045.     {
  2046.       int l = if_tok->line ();
  2047.       int c = if_tok->column ();
  2048.  
  2049.       retval = new tree_if_command (list, l, c);
  2050.     }
  2051.  
  2052.   return retval;
  2053. }
  2054.  
  2055. // Build an elseif clause.
  2056.  
  2057. static tree_if_clause *
  2058. make_elseif_clause (tree_expression *expr, tree_statement_list *list)
  2059. {
  2060.   maybe_warn_assign_as_truth_value (expr);
  2061.  
  2062.   return new tree_if_clause (expr, list);
  2063. }
  2064.  
  2065. // Finish a switch command.
  2066.  
  2067. static tree_switch_command *
  2068. finish_switch_command (token *switch_tok, tree_expression *expr,
  2069.                tree_switch_case_list *list, token *end_tok)
  2070. {
  2071.   tree_switch_command *retval = 0;
  2072.  
  2073.   if (! check_end (end_tok, token::switch_end))
  2074.     {
  2075.       int l = switch_tok->line ();
  2076.       int c = switch_tok->column ();
  2077.  
  2078.       retval = new tree_switch_command (expr, list, l, c);
  2079.     }
  2080.  
  2081.   return retval;
  2082. }
  2083.  
  2084. // Build a switch case.
  2085.  
  2086. static tree_switch_case *
  2087. make_switch_case (tree_expression *expr, tree_statement_list *list)
  2088. {
  2089.   maybe_warn_variable_switch_label (expr);
  2090.  
  2091.   return new tree_switch_case (expr, list);
  2092. }
  2093.  
  2094. // Build an assignment to a variable.
  2095.  
  2096. static tree_expression *
  2097. make_simple_assignment (tree_index_expression *var, token *eq_tok,
  2098.             tree_expression *expr)
  2099. {
  2100.   int l = eq_tok->line ();
  2101.   int c = eq_tok->column ();
  2102.  
  2103.   return new tree_simple_assignment_expression (var, expr, 0, 0, l, c);
  2104. }
  2105.  
  2106. // Make an expression that handles assignment of multiple values.
  2107.  
  2108. static tree_expression *
  2109. make_multi_val_ret (tree_matrix_row *mr, tree_expression *rhs, token *eq_tok)
  2110. {
  2111. // Convert the matrix list to a list of identifiers.  If that fails,
  2112. // we can abort here, without losing anything -- no other possible
  2113. // syntax is valid if we've seen the equals sign as the next token
  2114. // after the `]'. 
  2115.  
  2116.   tree_expression *retval = 0;
  2117.  
  2118.   lexer_flags.maybe_screwed_again--;
  2119.  
  2120.   tree_return_list *id_list = mr->to_return_list ();
  2121.  
  2122.   if (id_list)
  2123.     {
  2124.       int list_len = id_list->length ();
  2125.  
  2126.       if (list_len == 1)
  2127.     {
  2128.       tree_index_expression *lhs = id_list->remove_front ();
  2129.  
  2130.       int l = eq_tok->line ();
  2131.       int c = eq_tok->column ();
  2132.  
  2133.       retval = new tree_simple_assignment_expression (lhs, rhs,
  2134.                               0, 0, l, c);
  2135.     }
  2136.       else if (list_len > 1)
  2137.     {
  2138.       if (rhs->is_multi_val_ret_expression ())
  2139.         {
  2140.           tree_multi_val_ret *t = (tree_multi_val_ret *) rhs;
  2141.  
  2142.           int l = eq_tok->line ();
  2143.           int c = eq_tok->column ();
  2144.  
  2145.           retval = new tree_multi_assignment_expression (id_list, t,
  2146.                                  0, l, c);
  2147.         }
  2148.       else
  2149.         yyerror ("RHS must be an expression that returns multiple values");
  2150.     }
  2151.       else
  2152.     panic_impossible ();
  2153.     }
  2154.   else
  2155.     yyerror ("invalid identifier list for assignment");
  2156.  
  2157.   return retval;
  2158. }
  2159.  
  2160. // Begin defining a function.
  2161.  
  2162. static tree_function *
  2163. start_function_def (tree_parameter_list *param_list,
  2164.             tree_statement_list *body)
  2165. {
  2166.   body->mark_as_function_body ();
  2167.  
  2168.   tree_function *fcn = new tree_function (body, curr_sym_tab);
  2169.  
  2170.   fcn->define_param_list (param_list);
  2171.  
  2172.   return fcn;
  2173. }
  2174.  
  2175. // Do most of the work for defining a function.
  2176.  
  2177. static tree_function *
  2178. frob_function_def (tree_identifier *id, tree_function *fcn)
  2179. {
  2180.   string id_name = id->name ();
  2181.  
  2182.   // If input is coming from a file, issue a warning if the name of
  2183.   // the file does not match the name of the function stated in the
  2184.   // file.  Matlab doesn't provide a diagnostic (it ignores the stated
  2185.   // name).
  2186.  
  2187.   fcn->stash_function_name (id_name);
  2188.  
  2189.   if (reading_fcn_file)
  2190.     {
  2191.       if (curr_fcn_file_name != id_name)
  2192.     {
  2193.       if (Vwarn_function_name_clash)
  2194.         warning ("function name `%s' does not agree with function\
  2195.  file name `%s'", id_name.c_str (), curr_fcn_file_full_name.c_str ());
  2196.  
  2197.       global_sym_tab->rename (id_name, curr_fcn_file_name);
  2198.  
  2199.       if (error_state)
  2200.         return 0;
  2201.  
  2202.       id_name = id->name ();
  2203.     }
  2204.  
  2205.       fcn->stash_function_name (id_name);
  2206.       fcn->stash_fcn_file_name ();
  2207.       fcn->stash_fcn_file_time (time (0));
  2208.       fcn->mark_as_system_fcn_file ();
  2209.     }
  2210.   else if (! (input_from_tmp_history_file || input_from_startup_file)
  2211.        && reading_script_file
  2212.        && curr_fcn_file_name == id_name)
  2213.     {
  2214.       warning ("function `%s' defined within script file `%s'",
  2215.            id_name.c_str (), curr_fcn_file_full_name.c_str ());
  2216.     }
  2217.  
  2218.   top_level_sym_tab->clear (id_name);
  2219.  
  2220.   id->define (fcn);
  2221.  
  2222.   id->document (help_buf);
  2223.  
  2224.   return fcn;
  2225. }
  2226.  
  2227. // Finish defining a function.
  2228.  
  2229. static tree_function *
  2230. finish_function_def (token *var, tree_function *fcn)
  2231. {
  2232.   symbol_record *sr = var->sym_rec ();
  2233.  
  2234.   int l = var->line ();
  2235.   int c = var->column ();
  2236.  
  2237.   tree_identifier *tmp = new tree_identifier (sr, l, c);
  2238.  
  2239.   tree_parameter_list *tpl = new tree_parameter_list (tmp);
  2240.  
  2241.   tpl->mark_as_formal_parameters ();
  2242.  
  2243.   return fcn->define_ret_list (tpl);
  2244. }
  2245.  
  2246. // Finish defining a function a different way.
  2247.  
  2248. static tree_function *
  2249. finish_function_def (tree_parameter_list *ret_list, tree_function *fcn)
  2250. {
  2251.   ret_list->mark_as_formal_parameters ();
  2252.  
  2253.   return fcn->define_ret_list (ret_list);
  2254. }
  2255.  
  2256. static tree_index_expression *
  2257. make_index_expression (tree_indirect_ref *indir, tree_argument_list *args)
  2258. {
  2259.   tree_index_expression *retval = 0;
  2260.  
  2261.   int l = indir->line ();
  2262.   int c = indir->column ();
  2263.  
  2264.   if (indir->is_identifier_only ())
  2265.     {
  2266.       indir->preserve_identifier ();
  2267.       retval = new tree_index_expression (indir->ident (), args, l, c);
  2268.       delete indir;
  2269.     }
  2270.   else
  2271.     retval =  new tree_index_expression (indir, args, l, c);
  2272.  
  2273.   return retval;
  2274. }
  2275.  
  2276. // Finish building a matrix list.
  2277.  
  2278. static tree_expression *
  2279. finish_matrix (tree_matrix *m)
  2280. {
  2281.   tree_expression *retval = 0;
  2282.  
  2283.   lexer_flags.maybe_screwed_again--;
  2284.  
  2285.   if (m->all_elements_are_constant ())
  2286.     {
  2287.       octave_value tmp = m->eval (0);
  2288.  
  2289.       if (! error_state)
  2290.     {
  2291.       tree_constant *tc_retval = new tree_constant (tmp);
  2292.  
  2293.       ostrstream buf;
  2294.  
  2295.       tree_print_code tpc (buf);
  2296.  
  2297.       m->accept (tpc);
  2298.  
  2299.       buf << ends;
  2300.  
  2301.       char *s = buf.str ();
  2302.  
  2303.       tc_retval->stash_original_text (s);
  2304.  
  2305.       delete [] s;
  2306.  
  2307.       delete m;
  2308.  
  2309.       retval = tc_retval;
  2310.     }
  2311.       else
  2312.     delete m;
  2313.     }
  2314.   else
  2315.     retval = m;
  2316.  
  2317.   return retval;
  2318. }
  2319.  
  2320. static void
  2321. maybe_warn_missing_semi (tree_statement_list *t)
  2322. {
  2323.   if (lexer_flags.defining_func && Vwarn_missing_semicolon)
  2324.     {
  2325.       tree_statement *tmp = t->rear();
  2326.  
  2327.       if (tmp->is_expression ())
  2328.     warning ("missing semicolon near line %d, column %d in file `%s'",
  2329.          tmp->line (), tmp->column (),
  2330.          curr_fcn_file_full_name.c_str ());
  2331.     }
  2332. }
  2333.  
  2334. static void
  2335. set_stmt_print_flag (tree_statement_list *list, char sep,
  2336.              bool warn_missing_semi)
  2337. {
  2338.   switch (sep)
  2339.     {
  2340.     case ';':
  2341.       {
  2342.     tree_statement *tmp = list->rear ();
  2343.     tmp->set_print_flag (0);
  2344.       }
  2345.       break;
  2346.  
  2347.     case 0:
  2348.     case ',':
  2349.     case '\n':
  2350.     case '\r':
  2351.       if (warn_missing_semi)
  2352.     maybe_warn_missing_semi (list);
  2353.       break;
  2354.  
  2355.     default:
  2356.       warning ("unrecognized separator type!");
  2357.       break;
  2358.     }
  2359. }
  2360.  
  2361. static int
  2362. warn_assign_as_truth_value (void)
  2363. {
  2364.   Vwarn_assign_as_truth_value
  2365.     = check_preference ("warn_assign_as_truth_value");
  2366.  
  2367.   return 0;
  2368. }
  2369.  
  2370. static int
  2371. warn_comma_in_global_decl (void)
  2372. {
  2373.   Vwarn_comma_in_global_decl = check_preference ("warn_comma_in_global_decl");
  2374.  
  2375.   return 0;
  2376. }
  2377.  
  2378. static int
  2379. warn_function_name_clash (void)
  2380. {
  2381.   Vwarn_function_name_clash = check_preference ("warn_function_name_clash");
  2382.  
  2383.   return 0;
  2384. }
  2385.  
  2386. static int
  2387. warn_missing_semicolon (void)
  2388. {
  2389.   Vwarn_missing_semicolon = check_preference ("warn_missing_semicolon");
  2390.  
  2391.   return 0;
  2392. }
  2393.  
  2394. static int
  2395. warn_variable_switch_label (void)
  2396. {
  2397.   Vwarn_variable_switch_label
  2398.     = check_preference ("warn_variable_switch_label");
  2399.  
  2400.   return 0;
  2401. }
  2402.  
  2403. void
  2404. symbols_of_parse (void)
  2405. {
  2406.   DEFVAR (warn_assign_as_truth_value, 1.0, 0, warn_assign_as_truth_value,
  2407.     "produce warning for assignments used as truth values");
  2408.  
  2409.   DEFVAR (warn_comma_in_global_decl, 1.0, 0, warn_comma_in_global_decl,
  2410.     "produce warning for commas in global declarations");
  2411.  
  2412.   DEFVAR (warn_function_name_clash, 1.0, 0, warn_function_name_clash,
  2413.     "produce warning if function name conflicts with file name");
  2414.  
  2415.   DEFVAR (warn_missing_semicolon, 0.0, 0, warn_missing_semicolon,
  2416.     "produce a warning if a statement in a function file is not\n\
  2417. terminated with a semicolon");
  2418.  
  2419.   DEFVAR (warn_variable_switch_label, 0.0, 0, warn_variable_switch_label,
  2420.     "produce warning for variables used as switch labels");
  2421. }
  2422.  
  2423. /*
  2424. ;;; Local Variables: ***
  2425. ;;; mode: text ***
  2426. ;;; End: ***
  2427. */
  2428.